<style lang="scss" scoped>
.compress {
  width: 100%;
  height: 100%;
  .compress-upload {
    height: 40px;
    width: 100%;
    overflow: hidden;
    display: flex;
    // justify-content: space-around;
  }
  .compress-container {
    width: 100%;
    height: calc(100% - 40px);
    display: flex;
    justify-content: space-between;
  }
  .upload-demo {
    width: 200px;
    height: 100%;
    margin-right: 5px;
    .el-upload-dragger {
      height: 100%;
      border-color: #555;
    }
    .el-upload.is-drag {
      height: 100%;
    }
  }
  .upload-content {
    height: 100%;
    display: flex;
    justify-content: space-around;
    align-items: center;
    font-size: 50px;
  }
  .compress-main {
    // width: 100%;
    flex: 1;
    height: 580px;
    border: 1px solid #000;
    border-radius: 5px;
    padding: 5px;
    box-sizing: border-box;
    overflow-y: auto;
    .compress-main-item {
      display: flex;
      align-items: center;
      justify-content: space-around;
      padding: 5px;
      box-sizing: border-box;
      border: 1px solid #aaa;
      border-radius: 5px;
      margin-bottom: 5px;
      &:hover {
        background-color: #eee;
      }
      .compress-main-sectionItem {
        align-items: center;
        display: flex;
        margin-left: 10px;
        label {
          width: 50px;
        }
      }
    }
  }
}
</style>
<template>
  <div class="compress">
    <div class="compress-upload">
      <el-button type="danger" @click="clearAll">清空列表</el-button>
      <el-button type="warning" @click="randomName">随机名称(uuid+yyyymmdd)</el-button>
      <el-button type="primary" @click="downloadAll">打包下载 .ZIP</el-button>
      <el-button type="primary" @click="downloadFileImg">下载全部文件</el-button>
    </div>
    <div class="compress-container">
      <div class="compress-upload-style">
        <el-upload
          class="upload-demo"
          accept=".jpg,.png,.jpeg,.gif,.zip"
          :before-upload="beforeUpload"
          :multiple="true"
          :drag="true"
          :show-file-list="false"
        >
          <div class="upload-content">
            <el-icon><Plus /></el-icon>
          </div>
        </el-upload>
      </div>
      <main class="compress-main">
        <div class="compress-main-item" v-for="(ele, i) in compressImageList" :key="i">
          <el-image
            style="width: 100px; height: 100px"
            :src="ele.base64"
            :preview-src-list="compressImageList.map((item) => item.base64)"
            :hide-on-click-modal="true"
            :initial-index="i"
          />
          <section class="compress-main-sectionItem">
            <label style="width: 80px">名称:</label>
            <el-input placeholder="文件名称" v-model="ele.name" />
            &nbsp;
            <el-button
              type="warning"
              @click="ele.name = uuidv4() + '_' + dayjs().format('YYYYMMDD')"
              size="small"
              >随机</el-button
            >
          </section>

          <section class="compress-main-sectionItem">
            <label style="width: 80px">后缀:</label>
            <el-select placeholder="图片后缀" v-model="ele.suffix">
              <el-option
                v-for="item in ['png', 'jpg', 'jpeg', 'gif']"
                :key="item"
                :label="item"
                :value="item"
              />
            </el-select>
          </section>
          <el-button type="primary" class="compress-clear" @click="downloadOne(ele)"
            >下载</el-button
          >
          <el-button type="danger" class="compress-clear" @click="deleteOne(i)">删除</el-button>
        </div>
      </main>
    </div>
  </div>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue'
import { fileToBase64, downloadFileBase64, downloadFile, Message } from '@/utils/index'
import { compressedImage } from './utils'
import JSZip from 'JSZip'
import { v4 as uuidv4 } from 'uuid'
import { Plus } from '@element-plus/icons-vue'
import dayjs from 'dayjs'
const compressImageList = ref([])
const localKey = '__compressImages__'

onMounted(() => {
  try {
    const __localData = localStorage.getItem(localKey)
    compressImageList.value = JSON.parse(__localData) || []
  } catch (error) {
    compressImageList.value = []
  }
})

const beforeUpload = async (file) => {
  let _name = file.name.split('.')
  if (_name[_name.length - 1] === 'zip') {
    const zip = new JSZip()
    // 读取ZIP文件
    zip.loadAsync(file).then(function (contents) {
      // 遍历ZIP文件中的所有文件
      Object.keys(contents.files).forEach(async function (filename) {
        const reader = new FileReader()
        reader.readAsDataURL(await contents.files[filename].async('blob'))
        reader.onload = () => {
          const base64 = reader.result
          compressedImage(base64, (res) => {
            _name = filename.split('.')
            compressImageList.value.push({
              name: _name[0] || '',
              suffix: _name[_name?.length - 1] || 'png',
              base64: res
            })
          })
        }
      })
    })
  } else {
    const base64File = await fileToBase64(file)
    compressedImage(base64File, (res) => {
      compressImageList.value.push({
        name: _name[0] || '',
        suffix: _name[1] || 'jpg',
        base64: res
      })
    })
  }

  return false
}

const deleteOne = (index) =>
  (compressImageList.value = compressImageList.value.filter((ele, i) => i !== index))

const downloadOne = (ele) => {
  const name = `${ele.name}.${ele.suffix}`
  downloadFileBase64(name, ele.base64)
  Message.success('成功')
}

const base64ToBlob = (code) => {
  let parts = code.split(';base64,')
  let contentType = parts[0].split(':')[1]
  let raw = window.atob(parts[1])
  let rawLength = raw.length
  let uInt8Array = new Uint8Array(rawLength)
  for (let i = 0; i < rawLength; ++i) {
    uInt8Array[i] = raw.charCodeAt(i)
  }
  return new Blob([uInt8Array], {
    type: contentType
  })
}

const downloadAll = async () => {
  if (
    [...new Set(compressImageList.value.map((ele) => ele.name + ele.suffix))].length !==
    compressImageList.value.length
  )
    return Message.error('文件名称重复,请修改后重试')
  const _name = '压缩图片_' + Date.now()
  const _zip = new JSZip()
  const zip = _zip.folder(_name)
  compressImageList.value.forEach((ele) => {
    const blob = base64ToBlob(ele.base64)
    zip.file(`${ele.name}.${ele.suffix}`, blob, { binary: true })
  })
  downloadFile(_name + '.zip', await zip.generateAsync({ type: 'blob' }))
  Message.success('成功')
}

const downloadFileImg = () => {
  compressImageList.value.forEach((ele) => {
    const name = `${ele.name}.${ele.suffix}`
    downloadFileBase64(name, ele.base64)
  })
  Message.success('成功')
}
const clearAll = () => {
  compressImageList.value = []
}

const randomName = () => {
  compressImageList.value = compressImageList.value.map((ele) => {
    return {
      ...ele,
      name: uuidv4() + '_' + dayjs().format('YYYYMMDD')
    }
  })
}

watch(
  () => compressImageList,
  () => {
    localStorage.setItem(localKey, JSON.stringify(compressImageList.value))
  },
  { deep: true }
)
</script>
